const ModbusClient = require("./ModbusClient");

/**
 * 增强型Modbus客户端，支持批量写入多个数组
 */
class EnhancedModbusClient extends ModbusClient {
  /**
   * 写入单个寄存器数组
   * @param {number} address - 起始寄存器地址
   * @param {array} values - 要写入的值数组
   * @returns {Promise<object>} 写入结果
   */
  async writeSingleRegisterArray(address, values) {
    if (!Array.isArray(values)) {
      throw new Error("Values must be an array");
    }

    if (!this.isConnected) {
      throw new Error("Client is not connected");
    }

    try {
      // 将值转换为寄存器格式
      const registers = this._convertValuesToRegisters(values);
      await this.enqueueWriteRequest(address, registers);
      return { success: true, address, values, registers };
    } catch (err) {
      throw new Error(
        `Failed to write registers at address ${address}: ${err.message}`
      );
    }
  }

  /**
   * 批量写入多个寄存器数组
   * @param {array} writeArrayRequests - 写入请求数组 [{address, values}, ...]
   * @returns {Promise<object>} 批量写入结果
   */
  async writeMultipleRegisterArrays(writeArrayRequests) {
    if (!Array.isArray(writeArrayRequests)) {
      throw new Error("Write requests must be an array");
    }

    if (!this.isConnected) {
      throw new Error("Client is not connected");
    }

    if (writeArrayRequests.length === 0) {
      return { success: true, results: [] };
    }

    try {
      // 准备所有写入请求
      const writeRequests = writeArrayRequests.map((request) => {
        const { address, values } = request;
        if (typeof address !== "number" || !Array.isArray(values)) {
          throw new Error(
            "Each request must have a numeric address and an array of values"
          );
        }
        const registers = this._convertValuesToRegisters(values);
        return { address, registers };
      });

      // 批量执行写入操作
      const promises = writeRequests.map((req) =>
        this.enqueueWriteRequest(req.address, req.registers)
      );

      // 等待所有写入操作完成
      const results = await Promise.all(promises);

      // 整理返回结果
      const detailedResults = writeRequests.map((req, index) => ({
        address: req.address,
        registers: req.registers,
        success: true,
        result: results[index],
      }));

      return { success: true, results: detailedResults };
    } catch (err) {
      throw new Error(
        `Failed to write multiple register arrays: ${err.message}`
      );
    }
  }

  /**
   * 将值数组转换为寄存器数组
   * @param {array} values - 值数组（支持整数和浮点数）
   * @returns {array} 寄存器数组
   */
  _convertValuesToRegisters(values) {
    const registers = [];

    for (const value of values) {
      if (Number.isInteger(value)) {
        // 整数直接转换为寄存器
        registers.push(value);
      } else if (typeof value === "number") {
        // 浮点数转换为两个寄存器
        const floatRegisters = this._floatToRegisters(value);
        registers.push(...floatRegisters);
      } else {
        // 其他类型转换为整数
        registers.push(parseInt(value) || 0);
      }
    }

    return registers;
  }

  /**
   * 将浮点数转换为寄存器数组
   * @param {number} value - 浮点数值
   * @returns {array} 包含两个寄存器值的数组
   */
  _floatToRegisters(value) {
    const buffer = Buffer.alloc(4);
    buffer.writeFloatLE(value, 0);
    const reg1 = buffer.readUInt16LE(0);
    const reg2 = buffer.readUInt16LE(2);
    return [reg1, reg2];
  }

  /**
   * 从寄存器数组读取浮点数
   * @param {array} registers - 寄存器数组
   * @param {number} offset - 偏移量
   * @returns {number} 浮点数值
   */
  _registersToFloat(registers, offset = 0) {
    const buffer = Buffer.alloc(4);
    buffer.writeUInt16LE(registers[offset], 0);
    buffer.writeUInt16LE(registers[offset + 1], 2);
    return buffer.readFloatLE(0);
  }

  /**
   * 写入32位浮点数数组到指定地址
   * @param {number} startAddress - 起始地址
   * @param {number[]} values - 要写入的数值数组
   * @returns {Promise<boolean>} 写入是否成功
   */
  async write32BitFloats(startAddress, values) {
    try {
      // 将数值转换为32位浮点数对应的寄存器值
      const registers = this._convertFloatsToRegisters(values);

      // 写入寄存器
      await this.enqueueWriteRequest(startAddress, registers);

      // console.log(
      //   `成功写入: 起始地址=${startAddress}, 数值=${JSON.stringify(values)}`
      // );
      return true;
    } catch (error) {
      console.error("写入失败:", error.message);
      return false;
    }
  }

  /**
   * 将32位浮点数数组转换为寄存器数组
   * @param {number[]} values - 要转换的数值数组
   * @returns {number[]} 转换后的寄存器值数组
   */
  _convertFloatsToRegisters(values) {
    let registers = [];
    values.forEach((value) => {
      // 每个32位浮点数转换为2个寄存器，合并到数组中
      registers = registers.concat(this._float32ToRegisters(value));
    });
    return registers;
  }

  /**
   * 将32位浮点数转换为两个16位寄存器值
   * @param {number} value - 要转换的32位浮点数
   * @returns {number[]} 两个16位寄存器值的数组
   */
  _float32ToRegisters(value) {
    const buffer = Buffer.alloc(4);
    buffer.writeFloatBE(value, 0); // 写入32位浮点数（大端模式）

    // 提取两个16位寄存器值
    const reg1 = buffer.readUInt16BE(0);
    const reg2 = buffer.readUInt16BE(2);

    // 返回寄存器顺序
    return [reg1, reg2];
  }
}

module.exports = EnhancedModbusClient;
